use serde::{Deserialize, Serialize};
use bytes::Bytes;
use pyo3::prelude::*;
use pyo3::types::PyBytes;
use crate::DataTransferObject;

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PriceLevel {
    #[pyo3(get, set)]
    pub price: f64,
    #[pyo3(get, set)]
    pub volume: u64,
}

#[pymethods]
impl PriceLevel {
    #[new]
    pub fn new(price: f64, volume: u64) -> Self {
        PriceLevel { price, volume }
    }

    fn __repr__(&self) -> String {
        format!("(price={}, volume={})", self.price, self.volume)
    }

    fn __eq__(&self, other: PyRef<'_, Self>) -> bool {
        *self == *other
    }
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct TickData {
    #[pyo3(get, set)]
    pub timestamp_us: u64, // 时间戳(microseconds)
    #[pyo3(get, set)]
    pub symbol: String, // 品种
    #[pyo3(get, set)]
    pub last: f64, // 最后成交价
    #[pyo3(get, set)]
    pub asks: Vec<PriceLevel>, // '卖'数组, 价格正序
    #[pyo3(get, set)]
    pub bids: Vec<PriceLevel>, // '买'数组, 价格倒序
    #[pyo3(get, set)]
    pub volumne: Option<u64>, // 成交量
    #[pyo3(get, set)]
    pub turnover: Option<f64>, // 成交额
    #[pyo3(get, set)]
    pub open_interest: Option<u64>, // 持仓量
}

impl DataTransferObject for TickData {
    // Derive
}

#[pymethods]
impl TickData {
    #[new]
    pub fn new(
        timestamp_us: u64,
        symbol: String,
        last: f64,
        asks: Vec<PriceLevel>,
        bids: Vec<PriceLevel>,
    ) -> Self {
        TickData {
            timestamp_us,
            symbol,
            last,
            asks,
            bids,
            volumne: None,
            turnover: None,
            open_interest: None,
        }
    }

    fn __repr__(&self) -> String {
        let asks = self.asks.iter().map(|o| format!("{:}/{:}", o.price, o.volume)).collect::<Vec<_>>().join(", ");
        let bids = self.bids.iter().map(|o| format!("{:}/{:}", o.price, o.volume)).collect::<Vec<_>>().join(", ");
        format!(
            "TickData(timestamp_us={}, symbol='{}', last={}, asks=[{}], bids=[{}], volumne={:?}, turnover={:?}, open_interest={:?})",
            self.timestamp_us, self.symbol, self.last, asks, bids, self.volumne, self.turnover, self.open_interest
        )
    }

    // 测试用代码, 一般用Message包装即可

    /// 将 TickData 序列化为 JSON 字节数组
    #[pyo3(name = "to_json_bytes")]
    pub fn py_to_json_bytes(&self, py: Python) -> PyResult<PyObject> {
        match self.to_json_bytes() {
            Ok(bytes) => Ok(PyBytes::new_bound(py, &bytes).into()),
            Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!("Serialization error: {}", e))),
        }
    }

    /// 从 JSON 字节数组反序列化 TickData
    #[staticmethod]
    #[pyo3(name = "from_json_bytes")]
    pub fn py_from_json_bytes(bytes: &Bound<'_, PyBytes>) -> PyResult<Self> {
        let bytes = Bytes::copy_from_slice(bytes.as_bytes());
        match Self::from_json_bytes(&bytes) {
            Ok(tick_data) => Ok(tick_data),
            Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!("Deserialization error: {}", e))),
        }
    }

    /// 将 TickData 序列化为二进制字节数组 (使用 bincode)
    #[pyo3(name = "to_binary_bytes")]
    pub fn py_to_binary_bytes(&self, py: Python) -> PyResult<PyObject> {
        match self.to_binary_bytes() {
            Ok(bytes) => Ok(PyBytes::new_bound(py, &bytes).into()),
            Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!("Serialization error: {}", e))),
        }
    }

    /// 从二进制字节数组反序列化 TickData (使用 bincode)
    #[staticmethod]
    #[pyo3(name = "from_binary_bytes")]
    pub fn py_from_binary_bytes(bytes: &Bound<'_, PyBytes>) -> PyResult<Self> {
        let bytes = Bytes::copy_from_slice(bytes.as_bytes());
        match Self::from_binary_bytes(&bytes) {
            Ok(tick_data) => Ok(tick_data),
            Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!("Deserialization error: {}", e))),
        }
    }

    /// 序列化为 JSON 字符串
    #[pyo3(name = "to_json")]
    pub fn py_to_json(&self) -> PyResult<String> {
        match serde_json::to_string(self) {
            Ok(json) => Ok(json),
            Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!("JSON serialization error: {}", e))),
        }
    }

    /// 从 JSON 字符串反序列化
    #[staticmethod]
    #[pyo3(name = "from_json")]
    pub fn py_from_json(json: &str) -> PyResult<Self> {
        match serde_json::from_str(json) {
            Ok(tick_data) => Ok(tick_data),
            Err(e) => Err(pyo3::exceptions::PyValueError::new_err(format!("JSON deserialization error: {}", e))),
        }
    }
}
